//go:build integration

package test

import (
	"context"
	"runtime/debug"
	"testing"
	"time"

	"v8s-api/test/support"
	task_synchronization "v8s-api/test/task-synchronization"
	"v8s/test/containers/mongodb"
)

type (
	suit struct {
		folder string
	}
)

func TestFeatures(t *testing.T) {
	// Arrange
	ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)

	mongodb := mongodb.StartContainer(ctx)
	defer mongodb.Terminate(context.Background())

	applicationContext := support.GetApplicationContext(ctx, mongodb)

	cancel()

	// Act
	suits := []suit{
		{"existing-tasks"},
	}

	for _, current := range suits {
		function := cleaned(applicationContext, safe(applicationContext, func(t *testing.T, ctx *support.ApplicationContext) {
			task_synchronization.Test(t, ctx, current.folder)
		}))
		t.Run(current.folder, function)
		t.Run(current.folder, safe(applicationContext, func(t *testing.T, ctx *support.ApplicationContext) {
			task_synchronization.TestGet(t, ctx, "task-synchronization/"+current.folder+"/"+"expected-get.json")
		}))
		t.Run(current.folder, safe(applicationContext, func(t *testing.T, ctx *support.ApplicationContext) {
			task_synchronization.TestList(t, ctx, "task-synchronization/"+current.folder+"/"+"expected-list.json")
		}))
		t.Run(current.folder, safe(applicationContext, func(t *testing.T, ctx *support.ApplicationContext) {
			task_synchronization.TestSearch(t, ctx, "task-synchronization/"+current.folder+"/"+"expected-search.json")
		}))
		t.Run(current.folder, safe(applicationContext, func(t *testing.T, ctx *support.ApplicationContext) {
			task_synchronization.TestUpdate(t, ctx)
			task_synchronization.TestSuspend(t, ctx)
			task_synchronization.TestResume(t, ctx)
			task_synchronization.TestDelete(t, ctx)
			task_synchronization.TestCreate(t, ctx)
			task_synchronization.TestCreateUP(t, ctx)
			ctx.MongoHelper.AssertProjects(t, "task-synchronization/"+current.folder+"/"+"expected-mongodb.json")
		}))

	}
	//time.Sleep(100 * time.Second)
}

func cleaned(ctx *support.ApplicationContext, block func(t *testing.T)) func(t *testing.T) {
	ctx.MongoHelper.Clear(context.Background())

	return block
}

func safe(ctx *support.ApplicationContext, block func(*testing.T, *support.ApplicationContext)) func(t *testing.T) {
	return func(t *testing.T) {
		defer func() {
			recovered := recover()
			if recovered != nil {
				debug.PrintStack()
				t.Error(recovered)
			}
		}()

		block(t, ctx)
	}
}
